﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using wwl.Domain.Entities.Rbac;

namespace wwl.DataAccess.Mappings.Rbac
{
  /// <summary>
  /// 用户实体映射配置类（EF Core 数据映射）
  /// 负责配置用户领域实体与数据库表 rbac_user 之间的映射关系和约束规则
  /// 设计目标：在保持领域模型纯洁性的同时，实现高效、安全的数据持久化策略
  /// </summary>
  public class UserMap : IEntityTypeConfiguration<User>
  {
    /// <summary>
    /// 配置用户实体的数据库映射细节
    /// </summary>
    /// <param name="builder">实体类型构建器，提供流畅API配置实体到数据库的映射规则</param>
    /// <remarks>
    /// 1. 表结构设计：严格对齐业务需求的字段定义，同时考虑性能优化和数据完整性
    /// 2. 约束配置：通过数据库层面约束保障数据质量，减少应用层校验的复杂性
    /// 3. 索引策略：针对查询场景设计合适的索引，平衡查询性能和写入开销
    /// 4. 命名规范：遵循项目统一的数据库对象命名规范，保持代码的可维护性
    /// </remarks>
    public void Configure(EntityTypeBuilder<User> builder)
    {
      // 指定表名：明确映射到 rbac_user 表，保持与 Camunda 命名风格的一致性
      builder.ToTable("rbac_user");

      // 配置主键：使用字符串类型主键，支持UUID和业务编码等多种ID生成策略
      builder.HasKey(x => x.Id);

      #region 属性映射配置
      // 主键映射：64字符长度支持多种ID格式，NOT NULL 约束确保实体标识的完整性
      builder.Property(x => x.Id)
          .HasColumnName("id")
          .HasMaxLength(64)
          .IsRequired();

      // 用户名映射：唯一索引保障用户名全局唯一，64字符长度适应多种命名规范
      builder.Property(x => x.Username)
          .HasColumnName("username")
          .HasMaxLength(64)
          .IsRequired();

      // 密码哈希映射：255字符长度兼容多种哈希算法输出，可空设计支持外部认证集成
      builder.Property(x => x.PasswordHash)
          .HasColumnName("password_hash")
          .HasMaxLength(255);

      // 用户全名映射：128字符长度支持国际化姓名格式，业务展示的核心字段
      builder.Property(x => x.FullName)
          .HasColumnName("full_name")
          .HasMaxLength(128);

      // 邮箱映射：128字符长度适应长域名邮箱地址，唯一索引支持邮箱登录和找回
      builder.Property(x => x.Email)
          .HasColumnName("email")
          .HasMaxLength(128);

      // 电话映射：32字符长度支持国际电话号码格式，可空设计适应不同业务场景
      builder.Property(x => x.Phone)
          .HasColumnName("phone")
          .HasMaxLength(32);

      // 状态映射：字符串存储提升可读性，检查约束确保状态值的合法性
      builder.Property(x => x.Status)
          .HasColumnName("status")
          .HasConversion<string>()
          .HasMaxLength(20)
          .IsRequired();

      // 租户标识映射：64字符长度与租户主键保持一致，可空设计支持系统级用户
      builder.Property(x => x.TenantId)
          .HasColumnName("tenant_id")
          .HasMaxLength(64);

      // 基础实体属性映射：继承自 BaseEntity 的审计字段和软删除支持
      builder.Property(x => x.CreatedTime)
          .HasColumnName("created_time")
          .IsRequired();

      builder.Property(x => x.UpdatedTime)
          .HasColumnName("updated_time")
          .IsRequired();

      builder.Property(x => x.CreatedBy)
          .HasColumnName("created_by")
          .HasMaxLength(64)
          .IsRequired();

      builder.Property(x => x.Remarks)
          .HasColumnName("remarks")
          .HasColumnType("text");

      builder.Property(x => x.IsDeleted)
          .HasColumnName("is_deleted")
          .HasDefaultValue(false);
      #endregion

      #region 索引配置
      // 用户名唯一索引：保障登录标识的唯一性，提升用户名查询性能
      builder.HasIndex(x => x.Username)
          .IsUnique()
          .HasDatabaseName("ix_rbac_user_username");

      // 租户索引：支持按租户查询用户列表，优化多租户数据隔离场景的查询性能
      builder.HasIndex(x => x.TenantId)
          .HasDatabaseName("ix_rbac_user_tenant_id");

      // 状态索引：支持按状态筛选用户，优化用户管理界面的查询效率
      builder.HasIndex(x => x.Status)
          .HasDatabaseName("ix_rbac_user_status");
      #endregion

      #region 约束配置
      // 状态检查约束：数据库层面保障用户状态值的合法性，防止非法状态数据入库
      builder.ToTable(tableBuilder =>
      {
        tableBuilder.HasCheckConstraint(
            "ck_rbac_user_status",
            "status IN ('ENABLED', 'DISABLED', 'LOCKED')"
        );
      });
      #endregion
    }
  }
}